package org.ala.distributed_transaction_commons.communication;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.util.StringUtils;

/**
 * 消息定义
 *
 * @author 骆毅(ala)
 * @date 2024年2月18日
 */
public class Message {
	
	
	/**
	 * 发送给协调者统一channel
	 */
	public final static String CHANNEL_COORDINATOR = "channel:distributed_transaction:to_coordinator:%d";
	/**
	 * 取发送给协调者消息的channel
	 */
	public static String channelCoordinator(String txId) {
		int shard = Math.abs(txId.hashCode() % CHANNEL_SHARD);
		return String.format(CHANNEL_COORDINATOR, shard);
	}
	/**
	 * 取发送给协调者的全部channel
	 */
	public static String[] allChannelCoordinator() {
		String[] channels = new String[CHANNEL_SHARD];
		for (int i = 0 ; i < CHANNEL_SHARD ; i++) {
			channels[i] = String.format(CHANNEL_COORDINATOR, i);
		}
		return channels;
	}
	/**
	 * 发送给参与者统一channel
	 */
	public final static String CHANNEL_PARTICIPANT = "channel:distributed_transaction:to_participant:%d";
	/**
	 * 取发送给参与者消息的channel
	 */
	public static String channelParticipant(String txId) {
		int shard = Math.abs(txId.hashCode() % CHANNEL_SHARD);
		return String.format(CHANNEL_PARTICIPANT, shard);
	}
	/**
	 * 取发送给参与者的全部channel
	 */
	public static String[] allChannelParticipant() {
		String[] channels = new String[CHANNEL_SHARD];
		for (int i = 0 ; i < CHANNEL_SHARD ; i++) {
			channels[i] = String.format(CHANNEL_PARTICIPANT, i);
		}
		return channels;
	}
	/**
	 * channel分片数
	 */
	public final static int CHANNEL_SHARD = 8;
	
	

	
	/******************************************************************************************************
	 * 
	 * 向参与者发送的消息模版
	 *
	 ******************************************************************************************************/
	/**
	 * 消息类型
	 */
	public final static String MSG_TYPE_TO_PARITICIPANT_CAN_COMMIT = "can_commit",
								MSG_TYPE_TO_PARITICIPANT_PRE_COMMIT = "pre_commit",
								MSG_TYPE_TO_PARITICIPANT_COMMIT = "commit",
								MSG_TYPE_TO_PARITICIPANT_FINISHED = "finished",
								MSG_TYPE_TO_PARITICIPANT_ROLLBACK = "rollback";
	/**
	 * can_commit消息
	 * %s[0] = 业务类型
	 * %s[1] = 分布式事务id
	 */
	final static String TO_PARTICIPANT_CAN_COMMIT = "distributed_transaction:to_pariticipant:" + MSG_TYPE_TO_PARITICIPANT_CAN_COMMIT + ":%s:%s";
	/**
	 * can_commit消息
	 */
	public static String toParticipantCanCommit(String biz, String txId) {
		return String.format(TO_PARTICIPANT_CAN_COMMIT, biz, txId);
	}
	/**
	 * pre_commit消息
	 * %s[0] = 业务类型
	 * %s[1] = 分布式事务id
	 */
	final static String TO_PARTICIPANT_PRE_COMMIT = "distributed_transaction:to_pariticipant:" + MSG_TYPE_TO_PARITICIPANT_PRE_COMMIT + ":%s:%s";
	/**
	 * pre_commit消息
	 */
	public static String toParticipantPreCommit(String biz, String txId) {
		return String.format(TO_PARTICIPANT_PRE_COMMIT, biz, txId);
	}
	/**
	 * commit消息
	 * %s[0] = 业务类型
	 * %s[1] = 分布式事务id
	 */
	final static String TO_PARTICIPANT_COMMIT = "distributed_transaction:to_pariticipant:" + MSG_TYPE_TO_PARITICIPANT_COMMIT + ":%s:%s";
	/**
	 * commit消息
	 */
	public static String toParticipantCommit(String biz, String txId) {
		return String.format(TO_PARTICIPANT_COMMIT, biz, txId);
	}
	/**
	 * finished消息
	 * %s[0] = 业务类型
	 * %s[1] = 分布式事务id
	 */
	final static String TO_PARTICIPANT_FINISHED = "distributed_transaction:to_pariticipant:" + MSG_TYPE_TO_PARITICIPANT_FINISHED + ":%s:%s";
	/**
	 * commit消息
	 */
	public static String toParticipantFinished(String biz, String txId) {
		return String.format(TO_PARTICIPANT_FINISHED, biz, txId);
	}
	/**
	 * rollback消息
	 * %s[0] = 业务类型
	 * %s[1] = 分布式事务id
	 */
	final static String TO_PARTICIPANT_ROLLBACK = "distributed_transaction:to_pariticipant:" + MSG_TYPE_TO_PARITICIPANT_ROLLBACK + ":%s:%s";
	/**
	 * rollback消息
	 */
	public static String toParticipantRollback(String biz, String txId) {
		return String.format(TO_PARTICIPANT_ROLLBACK, biz, txId);
	}
	
	
	
	/******************************************************************************************************
	 * 
	 * 向协调者发送的消息模版
	 *
	 ******************************************************************************************************/
	/**
	 * 消息类型
	 */
	public final static String MSG_TYPE_TO_COORDINATOR_BEGIN = "begin",
								MSG_TYPE_TO_COORDINATOR_CAN_COMMIT = "can_commit",
								MSG_TYPE_TO_COORDINATOR_PRE_COMMIT = "pre_commit",
								MSG_TYPE_TO_COORDINATOR_COMMITED = "commited",
								MSG_TYPE_TO_COORDINATOR_ROLLBACK = "rollback";
	/**
	 * begin消息
	 * %s[0] = 业务类型
	 * %s[1] = 分布式事务id
	 * %s[2] = 参与者id
	 */
	final static String TO_COORDINATOR_BEGIN = "distributed_transaction:to_coordinator:" + MSG_TYPE_TO_COORDINATOR_BEGIN + ":%s:%s:%s";
	/**
	 * can_commit消息
	 */
	public static String toCoordinatorBegin(String biz, String txId, String pid) {
		return String.format(TO_COORDINATOR_BEGIN, biz, txId, pid);
	}
	/**
	 * can_commit消息
	 * %s[0] = 业务类型
	 * %s[1] = 分布式事务id
	 * %s[2] = 参与者id
	 */
	final static String TO_COORDINATOR_CAN_COMMIT = "distributed_transaction:to_coordinator:" + MSG_TYPE_TO_COORDINATOR_CAN_COMMIT + ":%s:%s:%s";
	/**
	 * can_commit消息
	 */
	public static String toCoordinatorCanCommit(String biz, String txId, String pid) {
		return String.format(TO_COORDINATOR_CAN_COMMIT, biz, txId, pid);
	}
	/**
	 * pre_commit消息
	 * %s[0] = 业务类型
	 * %s[1] = 分布式事务id
	 * %s[2] = 参与者id
	 */
	final static String TO_COORDINATOR_PRE_COMMIT = "distributed_transaction:to_coordinator:" + MSG_TYPE_TO_COORDINATOR_PRE_COMMIT + ":%s:%s:%s";
	/**
	 * pre_commit消息
	 */
	public static String toCoordinatorPreCommit(String biz, String txId, String pid) {
		return String.format(TO_COORDINATOR_PRE_COMMIT, biz, txId, pid);
	}
	/**
	 * commited消息
	 * %s[0] = 业务类型
	 * %s[1] = 分布式事务id
	 * %s[2] = 参与者id
	 */
	final static String TO_COORDINATOR_COMMITED = "distributed_transaction:to_coordinator:" + MSG_TYPE_TO_COORDINATOR_COMMITED + ":%s:%s:%s";
	/**
	 * commited消息
	 */
	public static String toCoordinatorCommited(String biz, String txId, String pid) {
		return String.format(TO_COORDINATOR_COMMITED, biz, txId, pid);
	}
	/**
	 * rollback消息
	 * %s[0] = 业务类型
	 * %s[1] = 分布式事务id
	 * %s[2] = 参与者id
	 */
	final static String TO_COORDINATOR_ROLLBACK = "distributed_transaction:to_coordinator:" + MSG_TYPE_TO_COORDINATOR_ROLLBACK + ":%s:%s:%s";
	/**
	 * rollback消息
	 */
	public static String toCoordinatorRollback(String biz, String txId, String pid) {
		return String.format(TO_COORDINATOR_ROLLBACK, biz, txId, pid);
	}
	
	
	/**
	 * 解析消息中包含的信息
	 */
	static Pattern pattern = Pattern.compile("distributed_transaction:(to_\\w+):([\\w|_]+):([\\w|\\d|_]+):([\\w|\\d|-]+)(:.+)?");
	/**
	 * 解析消息内容
	 */
	public static MessageContent parseMessage(String msg) {
		Matcher matcher = pattern.matcher(msg);
		if (matcher.matches()) {
			String to = matcher.group(1);
			String msgType = matcher.group(2);
			String biz = matcher.group(3);
			String txId = matcher.group(4);
			String pid = null;
			try {
				pid = matcher.group(5);
				if (!StringUtils.isEmpty(pid) && pid.startsWith(":")) {pid = pid.substring(1, pid.length());}
			}catch (Exception e) {
			}
			
			return new MessageContent(to, msgType, biz, txId, pid);
		}
		return null;
	}
	
	
	/**
	 * 消息内容数据结构
	 */
	public static class MessageContent {
		protected String to;
		protected String biz;
		protected String msgType;
		protected String txId;
		protected String pid;
		public MessageContent(String to, String msgType, String biz, String txId, String pid) {
			super();
			this.to = to;
			this.msgType = msgType;
			this.biz = biz;
			this.txId = txId;
			this.pid = pid;
		}
		public String getTo() {
			return to;
		}
		public void setTo(String to) {
			this.to = to;
		}
		public String getMsgType() {
			return msgType;
		}
		public void setMsgType(String msgType) {
			this.msgType = msgType;
		}
		public String getBiz() {
			return biz;
		}
		public void setBiz(String biz) {
			this.biz = biz;
		}
		public String getTxId() {
			return txId;
		}
		public void setTxId(String txId) {
			this.txId = txId;
		}
		public String getPid() {
			return pid;
		}
		public void setPid(String pid) {
			this.pid = pid;
		}
	}
	
	
}
